package com.zjj.jvm.reference;

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;

/**
 * @author zhanglei.zjj
 * @description 演示软引用用法、软引用和引用队列联合使用、软引用的回收
 * @date 2023/3/14 21:28
 */
public class TestSoftReference {
    public static void main(String[] args) {
//        softReferenceBaseUse();
//        softReferenceWithQueue();
        softReferenceRecycling();
    }

    /**
     * 可以添加 -XX:PrintGC 参数，查看是不是做过GC回收
     */
    private static void softReferenceBaseUse() {
        Object obj1 = new Object();
        System.out.println("obj1 : " + obj1);
        SoftReference<Object> reference1 = new SoftReference<>(obj1);
        System.out.println("reference1 : " + reference1.get());

        // 把强引用置空
        obj1 = null;

        // 手动gc
        System.gc();

        // 查看软引用是否还在
        System.out.println("gc后 reference1 : " + reference1.get());
    }

    private static void softReferenceWithQueue() {
        Object obj2 = new Object();
        System.out.println("obj2 : " + obj2);
        ReferenceQueue<Object> queue = new ReferenceQueue<>();
        SoftReference<Object> reference2 = new SoftReference<>(obj2, queue);
        System.out.println("reference2 : " + reference2.get());

        // 把强引用置空
        obj2 = null;

        // 手动gc
        System.gc();

        System.out.println("gc后 reference2 : " + reference2.get());

    }

    /**
     * 软引用回收
     * 为了方便演示需要添加 -Xmx20M
     *
     */
    private static void softReferenceRecycling() {
        ReferenceQueue<Object> queue = new ReferenceQueue<>();
        SoftReference<Object> reference3 = new SoftReference<>(new byte[1024 * 1024 * 10], queue);
        System.out.println("reference3 : " + reference3.get());

        // 手动gc
        System.gc();

        // 查看软引用是否还在
        System.out.println("gc后 reference3 : " + reference3.get());

        // 再申请一个 10M 内存，此时内存肯定不够
        byte[] bytes = new byte[1024 * 1024 * 10];

        System.out.println("当堆内存不足时 reference3 : " + reference3.get());

        Reference<?> reference = queue.poll();
        System.out.println("queue reference : " + reference);
        System.out.println("queue reference object : " + reference.get());
    }

}
